#include "thread.h"
#include "Event.h"
#include "Mutex.h"

namespace wxtl
{
	class WorkerPool;

	class Work
	{
	public:
		virtual ~Work()
		{

		}
		virtual void DoWork() = 0;
	};

	template<class T>
	class FunctorWork :public Work
	{
	public:
		FunctorWork(const T& functor)
			:m_functor(functor)
		{

		}

		virtual void DoWork()
		{
			m_functor();
		}

	private:
		T m_functor;
	};

	template<class T, class Pointer>
	class FunctionPointer0Work :public Work
	{	
	public:
		FunctionPointer0Work(T* object, Pointer pointer)
			:m_object(object)
			,m_pointer(pointer)
		{

		}
	public:
		void DoWork()
		{
			(m_object->*m_pointer)();
		}
	private:
		T* m_object;
		Pointer m_pointer;
	};

	template<class T, class Pointer, class P1>
	class FunctionPointer1Work :public Work
	{	
	public:
		FunctionPointer1Work(T* object, Pointer pointer, P1 p1)
			:m_object(object)
			,m_pointer(pointer)
			,m_p1(p1)
		{

		}
	public:
		void DoWork()
		{
			(m_object->*m_pointer)(m_p1);
		}
	private:
		T* m_object;
		Pointer m_pointer;
		P1 m_p1;
	};

	template<class T, class Pointer, class P1, class P2>
	class FunctionPointer2Work :public Work
	{	
	public:
		FunctionPointer2Work(T* object, Pointer pointer, P1 p1, P2 p2)
			:m_object(object)
			,m_pointer(pointer)
			,m_p1(p1)
			,m_p2(p2)
		{

		}
	public:
		void DoWork()
		{
			(m_object->*m_pointer)(m_p1, m_p2);
		}
	private:
		T* m_object;
		Pointer m_pointer;
		P1 m_p1;
		P1 m_p2;
	};

	template<class T, class F>
	void SubmitWork(WorkerPool* pool, T* t, F f)
	{
		FunctionPointer0Work<T, F> work(t,f);
		//pool->submit(
	}

	template<class T, class F> 
	wxtl::Work* MakeWork(T* t, F f)
	{
		return (wxtl::Work*)new wxtl::FunctionPointer0Work<T, F>(t, f);
	}

	template<class T, class F, class P1> 
	wxtl::Work* MakeWork(T* t, F f, P1 p1)
	{
		return (wxtl::Work*)new wxtl::FunctionPointer1Work<T, F, P1>(t, f, p1);
	}

	template<class T, class F, class P1, class P2> 
	wxtl::Work* MakeWork(T* t, F f, P1 p1, P2 p2)
	{
		return (wxtl::Work*)new wxtl::FunctionPointer1Work<T, F, P1>(t, f, p1, p2);
	}


	class Worker : public wxtl::Thread
	{

		Worker(WorkerPool* parent);
		~Worker();

		virtual void threadProc();

	private:
		WorkerPool* m_parent;
		Work* m_work;
	};

	
}